package org.zjvis.datascience.service;

import com.alibaba.fastjson.JSONObject;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.zjvis.datascience.common.constant.NoticeConstant;
import org.zjvis.datascience.common.dto.PipelineDTO;
import org.zjvis.datascience.common.dto.PipelineInstanceDTO;
import org.zjvis.datascience.common.dto.ProjectDTO;
import org.zjvis.datascience.common.enums.NoticeTypeEnum;
import org.zjvis.datascience.common.enums.TaskInstanceStatus;
import org.zjvis.datascience.common.util.JwtUtil;
import org.zjvis.datascience.common.util.StringUtil;
import org.zjvis.datascience.service.mapper.PipelineInstanceMapper;

/**
 * @description PipelineInstance 数据视图实例 Service
 * @date 2021-11-04
 */
@Service
public class PipelineInstanceService {

    private final static Logger logger = LoggerFactory.getLogger("PipelineInstanceService");

    @Lazy
    @Autowired
    private PipelineService pipelineService;

    @Lazy
    @Autowired
    private NoticeService noticeService;

    @Lazy
    @Autowired
    private ProjectService projectService;

    @Autowired
    PipelineInstanceMapper pipelineInstanceMapper;


    public Long save(PipelineInstanceDTO pipelineInstanceDTO) {
        pipelineInstanceMapper.save(pipelineInstanceDTO);
        return pipelineInstanceDTO.getId();
    }

    public PipelineInstanceDTO queryById(Long id) {
        return pipelineInstanceMapper.queryById(id);
    }

    public List<PipelineInstanceDTO> queryByPipelineId(Long pipelineId) {
        return pipelineInstanceMapper.queryByPipelineId(pipelineId);
    }

    public void update(PipelineInstanceDTO pipelineInstanceDTO) {
        pipelineInstanceMapper.update(pipelineInstanceDTO);
    }

    /**
     * 创建pipelineInstance
     * @param pipelineId
     * @return
     */
    public PipelineInstanceDTO createInstance(Long pipelineId) {
        PipelineDTO pipeline = pipelineService.queryById(pipelineId);
        PipelineInstanceDTO pipelineInstance = new PipelineInstanceDTO();
        pipelineInstance.setPipelineId(pipelineId);
        pipelineInstance.setUserId(JwtUtil.getCurrentUserId());
        pipelineInstance.setProjectId(pipeline.getProjectId());
        pipelineInstance.setGmtRunning(LocalDateTime.now());
        pipelineInstance.setStatus(TaskInstanceStatus.CREATE.toString());
        return pipelineInstance;
    }

    public void updateStatus(Long id, String status) {
        PipelineInstanceDTO pipelineInstance = this.queryById(id);
        pipelineInstance.setStatus(status);
        if (TaskInstanceStatus.FAIL.toString().equals(status) ||
            TaskInstanceStatus.KILLED.toString().equals(status) ||
            TaskInstanceStatus.STOP.toString().equals(status) ||
            TaskInstanceStatus.SUCCESS.toString().equals(status)) {
            Duration duration = Duration
                .between(pipelineInstance.getGmtRunning(), LocalDateTime.now());
            pipelineInstance.setDuringTime(duration.toMillis());
            if (duration.toMillis() > 60000) {
                try {
                    //执行时间超过60秒，发送消息通知
                    ProjectDTO project = projectService.query(pipelineInstance.getProjectId());
                    if (project != null) {
                        JSONObject process = new JSONObject();
                        process.put("pipelineId", pipelineInstance.getPipelineId());
                        process.put("projectId", pipelineInstance.getProjectId());
                        process.put("userId", JwtUtil.getCurrentUserId());
                        String time = (double) duration.toMillis() / 1000 + "s";
                        String content = String.format(NoticeConstant.PIPELINE_RUN_OVERTIME_CONTENT,
                            StringUtil.addHtmlBoldLabel(project.getName()), StringUtil.addHtmlBoldLabel(time));
                        noticeService.saveAndSendToUser(JwtUtil.getCurrentUserId(),
                            NoticeConstant.PIPELINE_RUN_OVERTIME_TITLE, content,
                            process.toJSONString(),
                            NoticeTypeEnum.project.getType(), JwtUtil.getCurrentUserId());
                    }

                } catch (Exception e) {
                    logger.error("pipeline执行超过1分钟，发送消息失败", e);
                }
            }
            this.update(pipelineInstance);
        }
    }

    public PipelineInstanceDTO getLatestInstance(Long pipelineId) {
        return pipelineInstanceMapper.getLatestInstance(pipelineId);
    }
}
